#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

using namespace std;

// int main()
//{
//   condition_variable cond;
//   mutex mu;
//   bool flag = false;
//   int num = 1;
//   int cnt = 100;
//
//   thread oddTh([&](){
//       while(true)
//       {
//         unique_lock<mutex> ul(mu);
//         if(flag) { cond.wait(ul); }
//         cout << this_thread::get_id() << ": " << num++ << endl;
//         flag = true;
//         cond.notify_one();
//         if(num >= cnt) { break; }
//       }
//   });
//   thread evenTh([&](){
//       while(true)
//       {
//         unique_lock<mutex> ul(mu);
//         if(!flag) { cond.wait(ul); }
//         cout << this_thread::get_id() << ": " << num++ << endl;
//         flag = false;
//         cond.notify_one();
//         if(num >= cnt) { break; }
//       }
//   });
//   oddTh.join();
//   evenTh.join();
//   return 0;
// }

typedef void* T;
//
//uint64_t exitcode = 6;
//
//void *routine(T args)
//{
//  uint64_t n = (uint64_t)args;
//  for(uint64_t i = 1; i <= n; ++i) {
//    cout << i << "> i am a thread, tid:" << pthread_self() << endl;
//  }
//  pthread_exit((T)exitcode);
//}
//
//int main()
//{
//
//  pthread_t th;
//  uint64_t n = 100;
//  pthread_create(&th, nullptr, routine, (T)n);
//  uint64_t retval = 0;
//  pthread_join(th, (T*)&retval);
//  printf("thread exit, code:%ld\n", retval);
//  return 0;
//}

__thread int n = 0;
//int n = 0;
int cnt = 10;

void* routine_1(T args)
{
  for(int i = 0; i < cnt; ++i) {
    cout << "i am th1, tid:" << pthread_self() << ", cur num: " << n << endl;
    ++n;
  }
}

void* routine_2(T args)
{
  for(int i = 0; i < cnt; ++i) {
    cout << "i am th2, tid:" << pthread_self() << ", cur num: " << n << endl;
  ++n;
  }
}

int main()
{
  pthread_t th1;
  pthread_t th2;
  pthread_create(&th1, nullptr, routine_1, nullptr);
  pthread_create(&th2, nullptr, routine_2, nullptr);
  pthread_join(th1, nullptr);
  pthread_join(th2, nullptr);
  return 0;
}
